<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      /**
       * 首先，Generator函数是ES6提供的一种异步编程解决方案，语法行为与传统函数完全不同。
       * 从语法上，可以理解成一个状态机，封装了多个内部状态。
       *
       * 执行Generator函数会返回一个遍历器对象，也就是说。Generator函数，除了状态机，还是一个遍历器对象生成函数。
       * 返回的遍历器对象，可以依次遍历Generator函数内部的每一个状态
       *
       * 从形式上。Generator函数是一个普通函数，但是有俩个特征。一是，function关键字与函数名之间有一个星号；
       * 二是，函数体内部使用yeild表达式，。定义不同内部状态(yield在英语里的意思就是“产出”)
       */
      function* helloWorldGenerator() {
        yield "hello";
        yield "world";
        return "ending";
      }
      var hw = helloWorldGenerator();
      console.log("hw", hw); // helloWorldGenerator {<suspended>}
      /**
       * 上面代码定义了一个Generator函数,它内部有俩个yeild表达式，即该函数有三个状态： hello , world, 和
       * return 语句(结束执行)
       *
       * 然后，Generator函数的调用方法与普通函数一样，也是在函数名后面加上一对圆括号。
       * 不同的是，调用Generator函数后，该函数并不执行！！返回的也不是函数运行结果，而是一个指向内部状态的指针对象。。。
       * 也就上一章提到的遍历器对象，(Iterator Object)
       *
       * 下一步，必须调用遍历器对象的next方法，使得指针指向下一个状态，也就是说，每次调用next方法，内部指针就从函数头部
       * 或上一次停下来的地方开始执行，直到遇到下一个yield表达式或者return语句，
       *
       * 换言之，Generator函数是分段执行的，yield表达式是暂停执行的标记，而next方法可以恢复执行
       */
      console.log(hw.next()); // {value: 'hello', done: false}
      hw.next();
      // { value: 'world', done: false }

      hw.next();
      // { value: 'ending', done: true }

      hw.next();
      // { value: undefined, done: true }
    </script>
  </body>
</html>
